package com.mall.user.services;

import com.google.gson.Gson;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.UserSerivce;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.converter.UserConverterMapper;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.entitys.TokenEx;
import com.mall.user.dal.entitys.UserVerify;
import com.mall.user.dal.persistence.MemberMapper;
import com.mall.user.dal.persistence.UserVerifyMapper;
import com.mall.user.dto.*;
import com.mall.user.dto.CheckUserLoginResponse;
import com.mall.user.dto.UserLoginRequest;
import com.mall.user.dto.UserLoginResponse;
import com.mall.user.utils.JwtTokenUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Component
@Service(interfaceClass = UserSerivce.class)
public class UserServiceImpl implements UserSerivce {

    //转换器
    @Autowired
    UserConverterMapper userConverterMapper;

    //Mapper
    @Autowired
    MemberMapper memberMapper;

    @Autowired
    UserVerifyMapper verifyMapper;

    @Autowired
    JavaMailSender javaMailSender;

    /**
     *用于用户登录
     */
    @Override
    public UserLoginResponse userLogin(Map map) {
        String userName = (String)map.get("userName");
        String password = (String)map.get("userPwd");
        String loginkey = userName + password + "timrain";
//        String pwdkey = req.getUserName()+req.getUserPwd()+ UUID.randomUUID().toString();
        String passwordmd5 = DigestUtils.md5DigestAsHex(loginkey.getBytes());
        UserLoginRequest userLoginRequest = new UserLoginRequest();
        userLoginRequest.setUserName(userName);
        userLoginRequest.setPassword(passwordmd5);


        //1、首先检查输入来的参数是否合法
        userLoginRequest.requestCheck();



        //2、直接查数据，因为应该是激活过后的用户才会添加到member表中，所以不用判断其他条件
        //后来看可能不是这样的，那就先不加条件，以后要加条件的话应该是判断其是否激活
        Example example = new Example(Member.class);
        example.createCriteria().andEqualTo("username",userLoginRequest.getUserName());

        //2.2、改进，果然要激活，但是激活要查其他表

        //3、查询得到Member
        //这里只写一个吧，不用list了。因为我觉得当前激活的用户不可能大于1。后面认证的确不会。
        List<Member> members = memberMapper.selectByExample(example);


        //3.9、判断该用户是否激活
        boolean flag = false;
        if(members.size() != 0){
            //拿着用户名去激活表中查是否激活
            Example example1 = new Example(UserVerify.class);
            example1.createCriteria().andEqualTo("username",members.get(0).getUsername());
            List<UserVerify> userVerifies = verifyMapper.selectByExample(example1);
            String isVerify = userVerifies.get(0).getIsVerify();
            if("N".equals(isVerify)){
                flag = true;
            }
        }


        boolean isEmpty = true;
        if (members.size()!=0){
            isEmpty=false;
        }

        UserLoginResponse memberDto = null;
        if(!isEmpty) {
            //4、开始判断:
            memberDto = userConverterMapper.converter(members.get(0));
        }

        //补:取得token


        //判断查到的用户数为空的情况以及判断密码正不正确，是同一个
        if(isEmpty||!userLoginRequest.getPassword().equals(members.get(0).getPassword())){
            memberDto.setCode("003001");
            memberDto.setMsg(SysRetCodeConstants.getMessage("003001"));
        }else if(flag){
            memberDto.setCode("003006");
            memberDto.setMsg(SysRetCodeConstants.getMessage("003006"));
        }
        //5、转换为返回值需要的dto
        else{
        memberDto.setCode("000000");
        memberDto.setMsg("成功");}



        //6、放token，暂时放username吧
        //根据需要，放一个username和userid吧
        Integer id = memberDto.getId().intValue();
        String token = JwtTokenUtils.builder().msg(id.toString()).build().creatJwtToken();

        memberDto.setToken(token);



        return memberDto;
    }

    @Override
    public UserRegisterResponse register(UserRegisterRequest req) {
        UserRegisterResponse userRegisterResponse = new UserRegisterResponse();
        Date date1 = new Date();
        System.out.println(date1.toString());
        //判空验证
        req.requestCheck();
        //是否重复验证
        volidUserName(req);
        Member member = new Member();
        member.setPhone("123123123");
        member.setEmail(req.getEmail());
        member.setUsername(req.getUserName());
        String pwdkey = req.getUserName()+req.getUserPwd()+"timrain";
        String password = DigestUtils.md5DigestAsHex(pwdkey.getBytes());
        member.setPassword(req.getUserPwd());
        member.setCreated(new Date());
        member.setUpdated(new Date());

        int i = memberMapper.insertOneUser(member);
//        int insert = memberMapper.insert(member);
        if (i != 1){
            userRegisterResponse.setCode(SysRetCodeConstants.USER_REGISTER_FAILED.getCode());
            userRegisterResponse.setMsg(SysRetCodeConstants.USER_REGISTER_FAILED.getMessage());
            return userRegisterResponse;
        }
        //插入verfy表
        String uuidkey = member.getUsername()+member.getPassword()+ UUID.randomUUID().toString();
        String uuid = DigestUtils.md5DigestAsHex(uuidkey.getBytes());
        UserVerify userVerify = new UserVerify();
        userVerify.setUsername(req.getUserName());
        userVerify.setUuid(uuid);
        userVerify.setRegisterDate(new Date());
        userVerify.setIsExpire("N");
        userVerify.setIsVerify("N");
        int insert = verifyMapper.insert(userVerify);
        if (insert != 1){
            userRegisterResponse.setCode(SysRetCodeConstants.USER_REGISTER_FAILED.getCode());
            userRegisterResponse.setMsg(SysRetCodeConstants.USER_REGISTER_FAILED.getMessage());
            return userRegisterResponse;
        }
        //发送用户激活邮件
        sendEmail(uuid,req);

        userRegisterResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        userRegisterResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        return userRegisterResponse;
    }

    @Override
    public UserVerifyResponse verify(String uid, String username) {
        UserVerifyResponse userVerifyResponse = new UserVerifyResponse();
        UserVerify userVerify = new UserVerify();
        userVerify.setIsVerify("Y");
        Example example = new Example(UserVerify.class);
        example.createCriteria()
                .andEqualTo("uuid",uid)
                .andEqualTo("username",username);
        verifyMapper.updateByExampleSelective(userVerify,example);

        userVerifyResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        userVerifyResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return userVerifyResponse;
    }

    @Async
    void sendEmail(String uuid, UserRegisterRequest req) {
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setSubject("TimeRain用户激活");
        simpleMailMessage.setFrom("799305112@qq.com");
        simpleMailMessage.setTo(req.getEmail());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("http://localhost:8080/user/verify?uid=")
                .append(uuid)
                .append("&username=")
                .append(req.getUserName());
        simpleMailMessage.setText(stringBuilder.toString());
        javaMailSender.send(simpleMailMessage);
    }

    private void volidUserName(UserRegisterRequest req) {
        Example example = new Example(Member.class);
        example.createCriteria()
                .andEqualTo("username",req.getUserName());
        List<Member> members = memberMapper.selectByExample(example);
        if (members.size() != 0){
            throw new ValidateException(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getCode(),SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getMessage());
        }
    }


    @Override
    public CheckUserLoginResponse checkUserLogin(Integer userId) {
        Long userId2 = (long) userId;
        CheckUserLoginResponse checkUserLoginResponse = memberMapper.selectByUserId(userId2);
        return checkUserLoginResponse;
    }
}
